//
//  NSObject+Regex.m
//  来店易商家
//  正则验证
//  Created by zhengjianliang on 15/12/15.
//  Copyright © 2015年 又一城. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "NSObject+Regex.h"
#import "NSObject+Verification.h"
@implementation NSObject (Regex)

#pragma mark - 正则验证 - 银行卡

/**
 *  正则验证 - 银行卡
 *
 *  @param value 验证的值
 *
 *  @return YES or NO
 */
+ (BOOL)isMathBankCard:(NSString *)value {
    BOOL flag = NO;
    
    if (![NSObject ldy_isEmpty:value] && value.length > 0) {
        NSString *regex = @"^([0-9]{16}|[0-9]{18}|[0-9]{19})$";
        NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",regex];
        flag =[predicate evaluateWithObject:value];
    }
    return flag;
}

#pragma mark - 正则验证 - 手机号码

/**
 *  正则验证 - 手机号码
 *
 *  @param value 验证的值
 *
 *  @return YES or NO
 */
+ (BOOL)isMathMobile:(NSString *)value {
    BOOL flag = NO;
    if (![NSObject ldy_isEmpty:value] && value.length > 0) {
        NSString *regex =@"^1[356789]\\d{9}$";
//        /^1[356789]\d{9}$/
        NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",regex];
        flag =[predicate evaluateWithObject:value];
    }
    return flag;
}

#pragma mark - 正则验证 - 判断首字符是否为字母

/**
 *  正则验证 - 判断首字符是否为字母
 *
 *  @param value 验证的值
 *
 *  @return YES or NO
 */
+ (BOOL)isMathFirstCharacterLetter:(NSString *)value {
    BOOL flag = NO;
    if (![NSObject ldy_isEmpty:value] && value.length > 0) {
        NSString *regex = @"[A-Za-z]+";
        NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",regex];
        flag =[predicate evaluateWithObject:value];
    }
    return flag;
}

#pragma mark - 正则验证 - 只能输入中文和字母

/**
 *  正则验证 - 只能输入中文和字母
 *
 *  @param value 验证的值
 *
 *  @return YES or NO
 */
+ (BOOL)isMathChineseOrLetters:(NSString *)value {
    BOOL flag = NO;
    if (![NSObject ldy_isEmpty:value] && value.length > 0) {
        NSString *regex =@"^[a-zA-Z\u4e00-\u9fa5\\s]+$";
        NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",regex];
        flag =[predicate evaluateWithObject:value];
    }
    return flag;
}

#pragma mark - 正则验证 - 验证qq号码

/**
 *  正则验证 - 验证qq号码
 *
 *  @param value 验证的值
 *
 *  @return YES or NO
 */
+ (BOOL)isMathQQ:(NSString *)value {
    BOOL flag = NO;
    if (![NSObject ldy_isEmpty:value] && value.length > 0) {
        NSString *regex = @"[1-9][0-9]\{4,10}";
        NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",regex];
        flag =[predicate evaluateWithObject:value];
    }
    return flag;
}

#pragma mark - 正则验证 - 是否是正整数

/**
 *  正则验证 - 是否是正整数
 *
 *  @param value 验证的值
 *
 *  @return YES or NO
 */
+ (BOOL)isMathPositiveInteger:(NSString *)value {
    BOOL flag = NO;
    if (![NSObject ldy_isEmpty:value] && value.length > 0) {
        NSString *regex =@"^[0-9]*$";
        NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",regex];
        flag =[predicate evaluateWithObject:value];
    }
    return flag;
}

#pragma mark - 正则验证 - 只允许输入字母和数字

/**
 *  正则验证 - 只允许输入字母和数字
 *
 *  @param value 验证的值
 *
 *  @return YES or NO
 */
+ (BOOL)isMathLettersOrNumbers:(NSString *)value {
    BOOL flag = NO;
    if (![NSObject ldy_isEmpty:value] && value.length > 0) {
        NSString *regex=@"^[A-Za-z0-9]{1,45}$";
        NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",regex];
        flag =[predicate evaluateWithObject:value];
    }
    return flag;
}

#pragma mark - 正则验证 - 只允许输入字母和数字 长度范围最小是1，最大默认是100

/**
 *  正则验证 - 只允许输入字母和数字 长度范围最小是1，最大默认是100
 *
 *  @param value 验证的值
 *  @param from  长度范围开始，最小是1
 *  @param to    长度范围结束，最大默认是100
 *
 *  @return YES or NO
 */
+ (BOOL)isMathLettersOrNumbers:(NSString *)value andFrom:(int)from andTo:(int)to {
    BOOL flag = NO;
    if (![NSObject ldy_isEmpty:value] && value.length > 0) {
        from = from<=0?1:from;
        to = to<from?100:to;
        NSString *regex=[NSString stringWithFormat:@"^[a-zA-Z0-9]{%d,%d}",from,to];
        NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",regex];
        flag =[predicate evaluateWithObject:value];
    }
    return flag;
}

#pragma mark - 正则验证 -邮箱

/**
 *  正则验证 - 邮箱
 *
 *  @param value 验证的值
 *
 *  @return YES or NO
 */
+ (BOOL)isMathEmail:(NSString *)value {
    BOOL flag = NO;
    if (![NSObject ldy_isEmpty:value] && value.length > 0) {
        NSString *regex=@"^[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}$";
        NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",regex];
        flag =[predicate evaluateWithObject:value];
    }
    return flag;
}

#pragma mark - 正则验证 - 只允许输入中文、字母和数字

/**
 *  正则验证 - 只允许输入中文、字母和数字
 *
 *  @param value 验证的值
 *
 *  @return YES or NO
 */
+ (BOOL)isMathChineseOrLettersAndNumbers:(NSString *)value {
    BOOL flag = NO;
    if (![NSObject ldy_isEmpty:value] && value.length > 0) {
        NSString *regex = @"^[a-zA-Z0-9\u4e00-\u9fa5]+$";
        NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regex];
        flag =[predicate evaluateWithObject:value];
    }
    return flag;
}

#pragma mark - 正则验证 - 身份证号

/**
 *  身份证校验
 *
 *  @param sPaperId 身份证号字符串
 *
 *  @return 是否校验通过
 */
+ (BOOL)isMathIDCard:(NSString *)sPaperId {
    sPaperId = [sPaperId stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
    //判断位数
    if (sPaperId.length != 15 && sPaperId.length != 18) {
        return NO;
    }
    if ([sPaperId rangeOfString:@"x"].length > 0) {//不能有小写的x
        return NO;
    }
    
    NSString *carid = sPaperId;
    long lSumQT = 0 ;
    //加权因子
    int R[] = {7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2};
    //校验码
    unsigned char sChecker[11] = {'1','0','X','9','8','7','6','5','4','3','2'};
    //将15位身份证号转换为18位
    NSMutableString *mString = [NSMutableString stringWithString:sPaperId];
    if (sPaperId.length == 15) {
        [mString insertString:@"19" atIndex:6];
        long p =0;
        //        const char *pid = [mString UTF8String];
        for (int i =0; i<17; i++)
        {
            NSString * s = [mString substringWithRange:NSMakeRange(i, 1)];
            p += [s intValue] * R[i];
            //            p += (long)(pid-48) * R;//
            
        }
        int o = p%11;
        NSString *string_content = [NSString stringWithFormat:@"%c",sChecker[o]];
        [mString insertString:string_content atIndex:[mString length]];
        carid = mString;
    }
    
    //判断年月日是否有效
    //年份
    int strYear = [[NSObject getStringWithRange:carid Value1:6 Value2:4] intValue];
    //月份
    int strMonth = [[NSObject getStringWithRange:carid Value1:10 Value2:2] intValue];
    //日
    int strDay = [[NSObject getStringWithRange:carid Value1:12 Value2:2] intValue];
    NSTimeZone *localZone = [NSTimeZone localTimeZone];
    NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
    [dateFormatter setDateStyle:NSDateFormatterMediumStyle];
    [dateFormatter setTimeStyle:NSDateFormatterNoStyle];
    [dateFormatter setTimeZone:localZone];
    [dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
    NSDate *date = [dateFormatter dateFromString:[NSString stringWithFormat:@"%d-%d-%d 12:01:01",strYear,strMonth,strDay]];
    if (date == nil) {
        return NO;
    }
    carid = [carid uppercaseString];
    const char *PaperId = [carid UTF8String];
    //检验长度
    if (18!=strlen(PaperId)) {
        return NO;
    }
    //校验数字
    NSString * lst = [carid substringFromIndex:carid.length-1];
    char di = [carid characterAtIndex:carid.length-1];
    
    if (!isdigit(di)) {
        if ([lst isEqualToString:@"X"]) {
        }else{
            return NO;
        }
    }
    //验证最末的校验码
    lSumQT = 0;
    for (int i = 0; i<17; i++){
        NSString * s = [carid substringWithRange:NSMakeRange(i, 1)];
        lSumQT += [s intValue] * R[i];
    }
    if (sChecker[lSumQT%11] != PaperId[17]) {
        return NO;
    }
    return YES;
}

/**
 *  根据范围截取字符串
 *
 *  @param str 被截取的字符串
 *  @param v1  开始位置
 *  @param v2  结束位置
 *
 *  @return 截取好的字符串
 */
+ (NSString *)getStringWithRange:(NSString *)str Value1:(int)v1 Value2:(int)v2 {
    NSString * sub = [str substringWithRange:NSMakeRange(v1, v2)];
    return sub;
}

/**
 *  判断是否是URL
 *  @return Yes 是数组 No 不是数组
 */
+ (BOOL)isMathURL:(NSString *)value {
    BOOL flag = NO;
    if (![NSObject ldy_isEmpty:value] && [value length] > 0) {
        NSString *regex=@"^(http://|https://)?((?:[A-Za-z0-9]+-[A-Za-z0-9]+|[A-Za-z0-9]+)\\.)+([A-Za-z]+)[/\?\\:]?.*$";
        NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@",regex];
        flag =[predicate evaluateWithObject:value];
    }
    return flag;
}


/*
 *第二种方法，利用Emoji表情最终会被编码成Unicode，因此，
 *只要知道Emoji表情的Unicode编码的范围，
 *就可以判断用户是否输入了Emoji表情。
 */
- (BOOL)stringContainsEmoji:(NSString *)string {
    // 过滤所有表情。returnValue为NO表示不含有表情，YES表示含有表情
    __block BOOL returnValue = NO;
    [string enumerateSubstringsInRange:NSMakeRange(0, [string length]) options:NSStringEnumerationByComposedCharacterSequences usingBlock:^(NSString *substring, NSRange substringRange, NSRange enclosingRange, BOOL *stop) {
        
        const unichar hs = [substring characterAtIndex:0];
        // surrogate pair
        if (0xd800 <= hs && hs <= 0xdbff) {
            if (substring.length > 1) {
                const unichar ls = [substring characterAtIndex:1];
                const int uc = ((hs - 0xd800) * 0x400) + (ls - 0xdc00) + 0x10000;
                if (0x1d000 <= uc && uc <= 0x1f77f) {
                    returnValue = YES;
                }
            }
        } else if (substring.length > 1) {
            const unichar ls = [substring characterAtIndex:1];
            if (ls == 0x20e3) {
                returnValue = YES;
            }
        } else {
            // non surrogate
            if (0x2100 <= hs && hs <= 0x27ff) {
                returnValue = YES;
            } else if (0x2B05 <= hs && hs <= 0x2b07) {
                returnValue = YES;
            } else if (0x2934 <= hs && hs <= 0x2935) {
                returnValue = YES;
            } else if (0x3297 <= hs && hs <= 0x3299) {
                returnValue = YES;
            } else if (hs == 0xa9 || hs == 0xae || hs == 0x303d || hs == 0x3030 || hs == 0x2b55 || hs == 0x2b1c || hs == 0x2b1b || hs == 0x2b50) {
                returnValue = YES;
            }
        }
    }];
    return returnValue;
}

@end
